/*
 * Copyright (c) 2014, Mentor Graphics Corporation
 * Copyright (c) 2015 Xilinx, Inc.
 * Copyright (c) 2016 Freescale Semiconductor, Inc.
 * Copyright 2016-2021 NXP
 * Copyright 2021 ACRIOS Systems s.r.o.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef RPMSG_QUEUE_H_
#define RPMSG_QUEUE_H_

#include "rpmsg_lite.h"

/* Rpmsg队列句柄类型. */
typedef void *rpmsg_queue_handle;

/* RL_API_HAS_ZEROCOPY必须启用, RPMsg队列才能工作. */
#if defined(RL_API_HAS_ZEROCOPY) && (RL_API_HAS_ZEROCOPY == 1)

/*******************************************************************************
 * API
 ******************************************************************************/

/* 导出API函数 */

#if defined(__cplusplus)
extern "C" {
#endif

/**
 * @brief  队列接收回调函数类型, 需要注册到一个端点.
 * @param  payload 指向包含接收数据的缓冲区的指针.
 * @param  payload_len 接收数据的大小, 字节: 单位.
 * @param  src 指向从中接收数据的端点地址的指针.
 * @param  priv 指向创建端点时提供的私有数据的指针.
 * @return 返回RL_HOLD或RL_RELEASE释放或保留有效载荷的缓冲区.
 */
int32_t rpmsg_queue_rx_cb(void *payload, uint32_t payload_len, uint32_t src, void *priv);

/**
 * @brief  创建一个RPMsg队列, 可以用来阻塞接收.
 * @param  rpmsg_lite_dev RPMsg-Lite实例.
 * @param  queue_storage 指向RPMsg-Lite队列静态存储的指针.
 * @param  queue_ctxt 指向RPMsg-Lite队列静态上下文的指针.
 * @return 成功返回RPMsg队列句柄, 失败返回RL_NULL.
 */
#if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1)
rpmsg_queue_handle rpmsg_queue_create(struct rpmsg_lite_instance *rpmsg_lite_dev,
    uint8_t *queue_storage, rpmsg_static_queue_ctxt *queue_ctxt);
#else
rpmsg_queue_handle rpmsg_queue_create(struct rpmsg_lite_instance *rpmsg_lite_dev);
#endif

/**
 * @brief  销毁一个队列并清理. 不要销毁已注册到活动端点的队列.
 * @param  rpmsg_lite_dev RPMsg-Lite实例.
 * @param  q 要销毁的RPMsg队列句柄.
 * @return 返回函数执行状态.
 */
int32_t rpmsg_queue_destroy(struct rpmsg_lite_instance *rpmsg_lite_dev,
                            rpmsg_queue_handle q);

/**
 * @brief  阻塞接收函数. 可以从RTOS任务调用的接收函数的阻塞版本. 数据从接收缓冲区复制到用户
 *         提供的缓冲区. 这是RPMsg接收函数的“带副本的接收”版本. 此版本使用简单, 但需要将数
 *         据从共享内存复制到用户空间缓冲区. 用户没有义务或负担管理共享内存缓冲区.
 * @param  rpmsg_lite_dev RPMsg-Lite实例.
 * @param  q 要监听的RPMsg队列句柄.
 * @param  src 指向从中接收数据的端点地址的指针.
 * @param  data 指向接收数据被复制到的用户缓冲区的指针.
 * @param  maxlen 要复制的最大字节数(接收的缓冲区大小).
 * @param  len 指向一个int变量的指针, 该变量将包含实际复制到用户缓冲区中的字节数.
 * @param  timeout 等待消息的超时(单位: 毫秒). 值为0表示不等待(非阻塞调用). 值为
 *         0xffffffff的表示永远等待(阻塞调用).
 * @return 返回函数执行状态.
 */
int32_t rpmsg_queue_recv(struct rpmsg_lite_instance *rpmsg_lite_dev,
    rpmsg_queue_handle q, uint32_t *src, char *data, uint32_t maxlen,
    uint32_t *len, uint32_t timeout);

/**
 * @brief  阻塞接收函数. 可以从RTOS任务调用的接收函数的阻塞版本. 数据不会复制到用户应用程序
 *         缓冲中. 这是RPMsg接收函数的“零拷贝接收”版本. 没有数据拷贝. 只返回指向数据的指针.
 *         这个版本速度很快, 但它需要用户管理缓冲区分配. 具体来说, 用户必须决定何时不再使用
 *         缓冲区, 并调用适当的API来释放它, 参见rpmsg_queue_nocopy_free().
 * @param  rpmsg_lite_dev RPMsg-Lite实例.
 * @param  q 要监听的RPMsg队列句柄.
 * @param  src 指向从中接收数据的端点地址的指针.
 * @param  data 指向共享内存中存储接收数据的RPMsg缓冲区的指针.
 * @param  len 指向一个int变量的指针, 该变量将包含实际复制到用户缓冲区中的字节数.
 * @param  timeout 等待消息的超时(单位: 毫秒). 值为0表示不等待(非阻塞调用). 值为
 *         0xffffffff的表示永远等待(阻塞调用).
 * @return 返回函数执行状态.
 */
int32_t rpmsg_queue_recv_nocopy(struct rpmsg_lite_instance *rpmsg_lite_dev,
    rpmsg_queue_handle q, uint32_t *src, char **data, uint32_t *len,
    uint32_t timeout);

/**
 * @brief  该函数释放之前由rpmsg_queue_recv_nocopy()返回的缓冲区. 一旦使用了接收数据的
 *         零拷贝机制, 就必须调用此函数来释放缓冲区, 并使其可用于下一次数据传输.
 * @param  rpmsg_lite_dev RPMsg-Lite实例.
 * @param  data 指向必须释放的共享内存的RPMsg缓冲区的指针.
 * @return 返回函数执行状态.
 */
int32_t rpmsg_queue_nocopy_free(struct rpmsg_lite_instance *rpmsg_lite_dev, void *data);

/**
 * @brief  该函数返回队列中挂起的消息数.
 * @param  q RPMsg队列句柄.
 * @return 返回队列中挂起的消息数.
 */
int32_t rpmsg_queue_get_current_size(rpmsg_queue_handle q);

#if defined(__cplusplus)
}
#endif

#endif /* RL_API_HAS_ZEROCOPY */

#endif /* RPMSG_QUEUE_H_ */
